package com.yanyu.space.common.log.support;

import com.yanyu.space.common.core.util.AppContext;
import com.yanyu.space.common.log.handler.LogFactory;
import com.yanyu.space.common.log.handler.LogWorkerContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.cloud.sleuth.Span;
import org.springframework.cloud.sleuth.Tracer;

import java.util.Map;

/**
 * @author yanyu
 */
@Slf4j
public abstract class LogRunnable implements Runnable {
    private static final String DEFAULT_SPAN_NAME = "runnable";
    private Tracer tracer = AppContext.getBean(Tracer.class);
    private Span span;

    public LogRunnable(String name, Map<String, String> tags) {
        this.span = tracer.nextSpan().event("cs").name(name != null ? name : DEFAULT_SPAN_NAME);
        if (MapUtils.isNotEmpty(tags)) {
            for (Map.Entry<String, String> tag : tags.entrySet()) {
                span.tag(tag.getKey(), tag.getValue());
            }
        }
    }

    public LogRunnable(Map<String, String> tags) {
        this(null, tags);
    }

    public LogRunnable(String name) {
        this(name, null);
    }

    public LogRunnable() {
        this(null, null);
    }

    @Override
    public void run() {
        try (Tracer.SpanInScope spanInScope = tracer.withSpan(span.start());
             LogWorkerContext logWorkerContext = LogFactory.getInstance().start(span.context())) {
            proceed();
        } finally {
            span.end();
        }
    }

    private void proceed() {
        try {
            execute();
        } catch (Throwable e) {
            log.error("{}", e.getMessage(), e);
        }
    }

    protected abstract void execute();
}
